package com.example.pdftomarkdown.controller;

import com.example.pdftomarkdown.service.MarkdownConverterService;
import com.example.pdftomarkdown.service.PdfParserService;
import com.example.pdftomarkdown.service.PdfToWordConverterService;
import com.example.pdftomarkdown.service.PdfToImageConverterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * PDF转Markdown控制器
 * 提供文件上传和转换的Web接口
 */
@Controller
public class PdfToMarkdownController {

    @Autowired
    private PdfParserService pdfParserService;

    @Autowired
    private MarkdownConverterService markdownConverterService;
    
    @Autowired
    private PdfToWordConverterService pdfToWordConverterService;
    
    @Autowired
    private PdfToImageConverterService pdfToImageConverterService;

    /**
     * 首页 - 显示文件上传界面
     */
    @GetMapping("/")
    public String index(Model model) {
        model.addAttribute("title", "PDF转Markdown转换器");
        return "index";
    }

    /**
     * 处理文件上传并转换为Markdown
     * 
     * @param file 上传的PDF文件
     * @return 转换结果页面或错误信息
     */
    @PostMapping("/convert")
    public ResponseEntity<?> convertPdfToMarkdown(@RequestParam("file") MultipartFile file) {
        try {
            // 验证文件
            if (file.isEmpty()) {
                return ResponseEntity.badRequest()
                    .body(new ConversionResponse(false, "请选择要上传的PDF文件", null));
            }

            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".pdf")) {
                return ResponseEntity.badRequest()
                    .body(new ConversionResponse(false, "只支持PDF格式文件", null));
            }

            // 提取PDF文本内容
            String pdfText = pdfParserService.extractTextFromPdf(file);

            // 转换为Markdown格式
            String markdownContent = markdownConverterService.convertToMarkdown(pdfText, originalFilename);

            // 返回成功响应
            ConversionResponse response = new ConversionResponse(true, "转换成功", markdownContent);
            return ResponseEntity.ok(response);

        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest()
                .body(new ConversionResponse(false, e.getMessage(), null));
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ConversionResponse(false, "文件处理失败: " + e.getMessage(), null));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ConversionResponse(false, "转换过程中发生错误: " + e.getMessage(), null));
        }
    }

    /**
     * 下载转换后的Markdown文件
     * 
     * @param file 上传的PDF文件
     * @return Markdown文件下载响应
     */
    @PostMapping("/download")
    public ResponseEntity<byte[]> downloadMarkdown(@RequestParam("file") MultipartFile file) {
        try {
            // 验证并转换文件
            if (file.isEmpty() || file.getOriginalFilename() == null) {
                return ResponseEntity.badRequest().build();
            }

            String originalFilename = file.getOriginalFilename();
            String pdfText = pdfParserService.extractTextFromPdf(file);
            String markdownContent = markdownConverterService.convertToMarkdown(pdfText, originalFilename);

            // 生成下载文件名
            String downloadFilename = generateMarkdownFilename(originalFilename);
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            
            // 使用RFC 2231标准设置Content-Disposition，支持中文文件名
            try {
                String encodedFilename = URLEncoder.encode(downloadFilename, "UTF-8")
                    .replaceAll("\\+", "%20");
                headers.add("Content-Disposition", 
                    "attachment; filename*=UTF-8''" + encodedFilename);
            } catch (UnsupportedEncodingException e) {
                // 如果编码失败，使用安全的ASCII文件名
                String safeFilename = generateSafeFilename(originalFilename);
                headers.setContentDispositionFormData("attachment", safeFilename);
            }
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");

            byte[] content = markdownContent.getBytes(StandardCharsets.UTF_8);
            
            return ResponseEntity.ok()
                .headers(headers)
                .contentLength(content.length)
                .body(content);

        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    /**
     * 将PDF文件转换为Word文档并下载
     * 
     * @param file 上传的PDF文件
     * @return Word文件下载响应
     */
    @PostMapping("/convert-to-word")
    public ResponseEntity<byte[]> convertPdfToWord(@RequestParam("file") MultipartFile file) {
        try {
            // 验证文件
            if (file.isEmpty() || file.getOriginalFilename() == null) {
                return ResponseEntity.badRequest().build();
            }

            String originalFilename = file.getOriginalFilename();
            if (!originalFilename.toLowerCase().endsWith(".pdf")) {
                return ResponseEntity.badRequest().build();
            }

            // 转换为Word文档
            byte[] wordContent = pdfToWordConverterService.convertPdfToWord(file);

            // 生成下载文件名
            String downloadFilename = generateWordFilename(originalFilename);
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"));
            
            // 使用RFC 2231标准设置Content-Disposition，支持中文文件名
            try {
                String encodedFilename = URLEncoder.encode(downloadFilename, "UTF-8")
                    .replaceAll("\\+", "%20");
                headers.add("Content-Disposition", 
                    "attachment; filename*=UTF-8''" + encodedFilename);
            } catch (UnsupportedEncodingException e) {
                // 如果编码失败，使用安全的ASCII文件名
                String safeFilename = generateSafeWordFilename(originalFilename);
                headers.setContentDispositionFormData("attachment", safeFilename);
            }
            
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");

            return ResponseEntity.ok()
                .headers(headers)
                .contentLength(wordContent.length)
                .body(wordContent);

        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    /**
     * 获取PDF文件的图片信息
     * 
     * @param file 上传的PDF文件
     * @return PDF图片信息
     */
    @PostMapping("/pdf-image-info")
    @ResponseBody
    public ResponseEntity<?> getPdfImageInfo(@RequestParam("file") MultipartFile file) {
        try {
            PdfToImageConverterService.PdfImageInfo imageInfo = pdfToImageConverterService.getPdfImageInfo(file);
            return ResponseEntity.ok(imageInfo);
        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().body(new ConversionResponse(false, e.getMessage(), null));
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ConversionResponse(false, "文件处理失败: " + e.getMessage(), null));
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(new ConversionResponse(false, "获取文件信息失败: " + e.getMessage(), null));
        }
    }
    
    /**
     * 将PDF文件转换为图片并下载ZIP包
     * 每一页生成一个图片文件
     * 
     * @param file 上传的PDF文件
     * @return 包含所有页面图片的ZIP文件
     */
    @PostMapping("/convert-to-images")
    public ResponseEntity<byte[]> convertPdfToImages(@RequestParam("file") MultipartFile file) {
        try {
            // 验证文件
            if (file.isEmpty() || file.getOriginalFilename() == null) {
                return ResponseEntity.badRequest().build();
            }

            String originalFilename = file.getOriginalFilename();
            if (!originalFilename.toLowerCase().endsWith(".pdf")) {
                return ResponseEntity.badRequest().build();
            }

            // 转换为图片ZIP
            byte[] zipContent = pdfToImageConverterService.convertPdfToImages(file);

            // 生成下载文件名
            String downloadFilename = generateImageZipFilename(originalFilename);
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.parseMediaType("application/zip"));
            
            // 使用RFC 2231标准设置Content-Disposition，支持中文文件名
            try {
                String encodedFilename = URLEncoder.encode(downloadFilename, "UTF-8")
                    .replaceAll("\\+", "%20");
                headers.add("Content-Disposition", 
                    "attachment; filename*=UTF-8''" + encodedFilename);
            } catch (UnsupportedEncodingException e) {
                // 如果编码失败，使用安全的ASCII文件名
                String safeFilename = generateSafeImageZipFilename(originalFilename);
                headers.setContentDispositionFormData("attachment", safeFilename);
            }
            
            headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
            headers.add("Pragma", "no-cache");
            headers.add("Expires", "0");

            return ResponseEntity.ok()
                .headers(headers)
                .contentLength(zipContent.length)
                .body(zipContent);

        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
    
    /**
     * 获取PDF单页图片预览
     * 
     * @param file 上传的PDF文件
     * @param page 页面索引（从1开始）
     * @return 单页图片
     */
    @PostMapping("/preview-page")
    public ResponseEntity<byte[]> previewPage(@RequestParam("file") MultipartFile file, 
                                              @RequestParam(value = "page", defaultValue = "1") int page) {
        try {
            // 验证文件
            if (file.isEmpty()) {
                return ResponseEntity.badRequest().build();
            }

            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".pdf")) {
                return ResponseEntity.badRequest().build();
            }
            
            // 转换页面索引（从1开始转为从0开始）
            int pageIndex = page - 1;
            if (pageIndex < 0) {
                return ResponseEntity.badRequest().build();
            }

            // 转换单页为图片
            byte[] imageContent = pdfToImageConverterService.convertSinglePageToImage(file, pageIndex);

            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.IMAGE_PNG);
            headers.add("Cache-Control", "max-age=3600"); // 缓存1小时

            return ResponseEntity.ok()
                .headers(headers)
                .contentLength(imageContent.length)
                .body(imageContent);

        } catch (IllegalArgumentException e) {
            return ResponseEntity.badRequest().build();
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * API接口 - 获取转换统计信息
     */
    @GetMapping("/api/stats")
    @ResponseBody
    public ResponseEntity<ConversionStats> getStats() {
        ConversionStats stats = new ConversionStats();
        stats.setServerTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        stats.setMaxFileSize("10MB");
        stats.setSupportedFormats("PDF转Markdown, PDF转Word, PDF转图片");
        stats.setVersion("1.0.0");
        
        return ResponseEntity.ok(stats);
    }

    /**
     * 生成Markdown文件名
     */
    private String generateMarkdownFilename(String originalFilename) {
        String baseName = originalFilename.replaceAll("\\.[pP][dD][fF]$", "");
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return baseName + "_converted_" + timestamp + ".md";
    }
    
    /**
     * 生成Word文件名
     */
    private String generateWordFilename(String originalFilename) {
        String baseName = originalFilename.replaceAll("\\.[pP][dD][fF]$", "");
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return baseName + "_converted_" + timestamp + ".docx";
    }
    
    /**
     * 生成图片ZIP文件名
     */
    private String generateImageZipFilename(String originalFilename) {
        String baseName = originalFilename.replaceAll("\\.[pP][dD][fF]$", "");
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return baseName + "_images_" + timestamp + ".zip";
    }
    
    /**
     * 生成安全的ASCII文件名（当中文编码失败时使用）
     */
    private String generateSafeFilename(String originalFilename) {
        // 移除扩展名
        String baseName = originalFilename.replaceAll("\\.[pP][dD][fF]$", "");
        
        // 将中文和特殊字符替换为安全字符
        String safeName = baseName
            .replaceAll("[^a-zA-Z0-9\\-_]", "_")
            .replaceAll("_{2,}", "_")
            .replaceAll("^_|_$", "");
            
        // 如果文件名为空或太短，使用默认名称
        if (safeName.length() < 3) {
            safeName = "converted_document";
        }
        
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return safeName + "_" + timestamp + ".md";
    }
    
    /**
     * 生成安全的Word文件名（当中文编码失败时使用）
     */
    private String generateSafeWordFilename(String originalFilename) {
        // 移除扩展名
        String baseName = originalFilename.replaceAll("\\.[pP][dD][fF]$", "");
        
        // 将中文和特殊字符替换为安全字符
        String safeName = baseName
            .replaceAll("[^a-zA-Z0-9\\-_]", "_")
            .replaceAll("_{2,}", "_")
            .replaceAll("^_|_$", "");
            
        // 如果文件名为空或太短，使用默认名称
        if (safeName.length() < 3) {
            safeName = "converted_document";
        }
        
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return safeName + "_" + timestamp + ".docx";
    }
    
    /**
     * 生成安全的图片ZIP文件名（当中文编码失败时使用）
     */
    private String generateSafeImageZipFilename(String originalFilename) {
        // 移除扩展名
        String baseName = originalFilename.replaceAll("\\.[pP][dD][fF]$", "");
        
        // 将中文和特殊字符替换为安全字符
        String safeName = baseName
            .replaceAll("[^a-zA-Z0-9\\-_]", "_")
            .replaceAll("_{2,}", "_")
            .replaceAll("^_|_$", "");
            
        // 如果文件名为空或太短，使用默认名称
        if (safeName.length() < 3) {
            safeName = "converted_images";
        }
        
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
        return safeName + "_" + timestamp + ".zip";
    }

    /**
     * 转换响应类
     */
    public static class ConversionResponse {
        private boolean success;
        private String message;
        private String content;

        public ConversionResponse(boolean success, String message, String content) {
            this.success = success;
            this.message = message;
            this.content = content;
        }

        // Getters and Setters
        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }

        public String getContent() {
            return content;
        }

        public void setContent(String content) {
            this.content = content;
        }
    }

    /**
     * 转换统计信息类
     */
    public static class ConversionStats {
        private String serverTime;
        private String maxFileSize;
        private String supportedFormats;
        private String version;

        // Getters and Setters
        public String getServerTime() {
            return serverTime;
        }

        public void setServerTime(String serverTime) {
            this.serverTime = serverTime;
        }

        public String getMaxFileSize() {
            return maxFileSize;
        }

        public void setMaxFileSize(String maxFileSize) {
            this.maxFileSize = maxFileSize;
        }

        public String getSupportedFormats() {
            return supportedFormats;
        }

        public void setSupportedFormats(String supportedFormats) {
            this.supportedFormats = supportedFormats;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }
    }
}